package com.simple.system.service.impl;


import com.simple.common.constant.SystemRedisConstans;
import com.simple.framework.core.auth.JwtContext;
import com.simple.framework.core.redis.RedisService;
import com.simple.framework.utils.BeanCopyUtils;
import com.simple.system.domain.dto.AddSysMenuDto;
import com.simple.system.domain.entity.SysMenu;
import com.simple.system.domain.vo.SystemManagementRouterVo;
import com.simple.system.mapper.SysMenuMapper;
import com.simple.system.service.SysMenuService;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;

/**
 * @Description 菜单表(SysMenu)表服务实现类
 * @Author xiaoke
 * @Date 2024/8/10 18:00
 * @Version 1.0
 */
@Service("sysMenuService")
public class SysMenuServiceImpl  implements SysMenuService {

    private final SysMenuMapper sysMenuMapper;

    private final RedisService redisService;

    public SysMenuServiceImpl(SysMenuMapper sysMenuMapper, RedisService redisService) {
        this.sysMenuMapper = sysMenuMapper;
        this.redisService = redisService;
    }


    @Override
    public List<SysMenu> listMenu() {
        String key  = SystemRedisConstans.SYS_MENU;
        List<SysMenu> list = redisService.getCacheList(key);
        if(list != null && !list.isEmpty()) {
            return list;
        }
        list = getMenusTree(0L,sysMenuMapper.getMenusTree());
        redisService.setCacheList(key,list);
        return list;
    }

    @Override
    public List<SysMenu> listMenuPerms() {
        String key = SystemRedisConstans.SYS_MENU_PERMS;
        List<SysMenu> list = redisService.getCacheList(key);
        if(list != null && !list.isEmpty()) {
            return list;
        }
        list = getMenusTree(0L,sysMenuMapper.selectList(null));
        redisService.setCacheList(key,list);
        return list;
    }


    @Override
    public List<SystemManagementRouterVo> managementRouter() {
        String key = SystemRedisConstans.SYS_MENU_ROUTER + JwtContext.getUserId();
        List<SystemManagementRouterVo> list = redisService.getCacheList(key);
        if(list != null && !list.isEmpty()) {
            return list;
        }
        list = getRouterMenusTree(0L,sysMenuMapper.managementRouter());
        List<SysMenu> perms = sysMenuMapper.getByUserIdMenuPerms(JwtContext.getUserId());
        setPerms(list, perms);
        redisService.setCacheList(key,list);
        return list;
    }

    @Transactional
    @Override
    public Long create(AddSysMenuDto dto) {
        SysMenu sysMenu = BeanCopyUtils.copyBean(dto, SysMenu.class);
        if(sysMenu.getPid() == null) {
            sysMenu.setRank(null);
        }
        sysMenuMapper.insert(sysMenu);
        if(dto.getRoles() != null && !dto.getRoles().isEmpty()) {
            sysMenuMapper.insertMenuRoles(sysMenu.getId(),dto.getRoles());
        }
        clearCache();
        return sysMenu.getId();
    }

    @Override
    public void update(Long id, AddSysMenuDto dto) {
        SysMenu sysMenu = sysMenuMapper.selectById(id);
        if(sysMenu == null) {
            throw new RuntimeException("菜单不存在");
        }
        if(sysMenu.getPid() == null) {
            sysMenu.setRank(null);
        }
        BeanCopyUtils.copyNonNullProperties(dto, sysMenu);
        sysMenuMapper.deleteMenuRoles(id);
        if(dto.getRoles() != null && !dto.getRoles().isEmpty()){
            sysMenuMapper.insertMenuRoles(id,dto.getRoles());
        }
        sysMenuMapper.updateById(sysMenu);
        clearCache();
    }

    @Override
    public void delete(Long id) {
        sysMenuMapper.deleteById(id);
        clearCache();
    }

    /**
     * 递归获取菜单树
     * @param pid 父id
     * @param menus 菜单列表
     * @return List<SysMenu>
     */
    private List<SysMenu> getMenusTree(Long pid,List<SysMenu> menus) {
        List<SysMenu> children = new ArrayList<>();
        for (SysMenu menu : menus) {
            if (menu.getPid().equals(pid)) {
                children.add(menu);
                // 递归调用，获取子菜单的子菜单
                menu.setChildren(getMenusTree(menu.getId(), menus));
            }
        }
        return children;
    }

    /**
     * 递归获取路由菜单树
     * @param pid 父id
     * @param menus 菜单列表
     * @return List<SysMenu>
     */
    private List<SystemManagementRouterVo> getRouterMenusTree(Long pid,List<SystemManagementRouterVo> menus) {
        List<SystemManagementRouterVo> children = new ArrayList<>();
        for (SystemManagementRouterVo menu : menus) {
            if (menu.getPid().equals(pid)) {
                children.add(menu);
                // 递归调用，获取子菜单的子菜单
                menu.setChildren(getRouterMenusTree(menu.getId(), menus));
            }
        }
        return children;
    }


    private void clearCache() {
        redisService.deleteObject(SystemRedisConstans.SYS_MENU);
        redisService.deleteObject(SystemRedisConstans.SYS_MENU_PERMS);
        redisService.deleteObject(SystemRedisConstans.SYS_MENU_ROUTER + JwtContext.getUserId());
    }
    private void setPerms(List<SystemManagementRouterVo> systemManagementRouterVos, List<SysMenu> perms) {
        for (SystemManagementRouterVo routerVo : systemManagementRouterVos) {
            Set<String> auths = routerVo.getMeta().getAuths() != null ? routerVo.getMeta().getAuths() : new HashSet<>();
            // 遍历权限集合，找到与当前routerVo关联的权限并添加到auths集合中
            for (SysMenu perm : perms) {
                if (routerVo.getId().equals(perm.getPid())) {
                    auths.add(perm.getPerms());
                }
            }
            // 只有当auths集合内容有变化时才更新
            if (!auths.isEmpty()) {
                routerVo.getMeta().setAuths(auths);
            }
            // 处理子节点，避免空指针异常
            List<SystemManagementRouterVo> children = routerVo.getChildren();
            if (children != null && !children.isEmpty()) {
                setPerms(children, perms);
            }
        }
    }

}

